package main

import (
	"context"
	"errors"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"

	"go.uber.org/zap"
	_ "xincan.com.cn/tarot-go/api/openapi/v2"
	_ "xincan.com.cn/tarot-go/internal/components/cache"
	_ "xincan.com.cn/tarot-go/internal/components/config"
	_ "xincan.com.cn/tarot-go/internal/components/database"
	"xincan.com.cn/tarot-go/internal/components/logging"
	_ "xincan.com.cn/tarot-go/internal/components/orm"
	_ "xincan.com.cn/tarot-go/internal/components/registry"
	"xincan.com.cn/tarot-go/internal/tarot"

	"xincan.com.cn/tarot-go/router"
)

// init
// Title 			init
// Description		服务初始化信息
// Author			alittlexincan@163.com				2024/07/22 11:36
// Update			alittlexincan@163.com 				2024/07/22 11:36
func init() {

	tarot.InitBootstrapApplication() // 初始化Tarot
}

// @Title Tarot框架
// @version 0.0.2
// @Description Tarot框架
// @TermsOfService https://xincan.github.io
// @contact.name xincan
// @contact.url https://xincan.github.io
// @contact.email alittlexincan@163.com
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @BasePath /
func main() {

	// 1. 安装: brew install graphviz

	// 2. 导入: _ "net/http/pprof"

	// 3. 系统启动后执行以下命令
	//# 生成CPU性能分析的可交互网页（默认30秒采集）
	//go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile
	//
	//# 分析堆内存的分配情况
	//go tool pprof -http=:8080 http://localhost:6060/debug/pprof/heap
	//
	//# 查看当前所有Goroutine的运行状态，诊断协程泄漏
	//go tool pprof -http=:8080 http://localhost:6060/debug/pprof/goroutine

	//go func() {
	//	log.Println(http.ListenAndServe("localhost:6060", nil))
	//}()

	// 1. 初始化日志（确保最先初始化）
	defer func(logger *logging.TraceLogger) {
		_ = logging.Sync(logger)
	}(tarot.Logger)

	// 2. 启动HTTP服务
	srv := start()

	// 3. 统一信号处理与优雅关闭
	shutdown(srv)
}

// start
// Title 			start
// Description   	启动HTTP服务
// Author  			alittlexincan@163.com 				2024/07/22 11:36
// Update  			alittlexincan@163.com 				2024/07/22 11:36
func start() *http.Server {
	port := strconv.Itoa(tarot.App.Config.Port)
	srv := &http.Server{Addr: "0.0.0.0:" + port, Handler: router.Router()}
	tarot.Logger.Info("服务启动成功", zap.String("port", port))
	go func() {
		if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			tarot.Logger.Error("服务启动失败", zap.Any("err", err))
			panic("服务启动失败")
		}
	}()
	return srv
}

// shutdown
// Title 			shutdown
// Description   	统一信号处理与优雅关闭
// Author  			alittlexincan@163.com 				2024/07/22 11:36
// Update  			alittlexincan@163.com 				2024/07/22 11:36
// Param   			srv *http.Server  					HTTP服务实例
func shutdown(srv *http.Server) {
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	sig := <-quit
	tarot.Logger.Info("接收关闭信号", zap.String("signal", sig.String()))

	// 创建优雅关闭上下文（15秒超时）
	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	defer cancel()

	tarot.Logger.Info("开始关闭服务")
	if err := srv.Shutdown(ctx); err != nil {
		tarot.Logger.Fatal("强制关闭服务", zap.Error(err))
	}
	tarot.Logger.Info("释放服务资源")
	releaseResources() // 释放数据库等资源
	tarot.Logger.Info("服务完全关闭")
}

// releaseResources
// Title 			releaseResources
// Description   	释放资源
// Author  			alittlexincan@163.com 				2024/07/22 11:36
// Update  			alittlexincan@163.com 				2024/07/22 11:36
func releaseResources() {
	// 实际项目中替换为具体资源释放逻辑
	cacheClose()
	databaseClose()
}

// cacheClose
// Title 			cacheClose
// Description   	释放缓存资源
// Author  			alittlexincan@163.com 				2024/07/22 11:36
// Update  			alittlexincan@163.com 				2024/07/22 11:36
func cacheClose() {
	err := tarot.Cache.Close()
	if err != nil {
		tarot.Logger.Error("关闭缓存失败", zap.Any("err", err))
	} else {
		tarot.Logger.Info("关闭缓存成功")
	}
}

// databaseClose
// Title 			databaseClose
// Description   	释放数据库资源
// Author  			alittlexincan@163.com 				2024/07/22 11:36
// Update  			alittlexincan@163.com 				2024/07/22 11:36
func databaseClose() {
	if db, err := tarot.DB.DB(); err != nil {
		tarot.Logger.Error("关闭存储失败", zap.Any("err", err))
	} else {
		if err = db.Close(); err != nil {
			tarot.Logger.Error("关闭存储失败", zap.Any("err", err))
		}
		tarot.Logger.Info("关闭存储成功")
	}
}
